package com.bankcard.card;

public class LuhnValidator {

    private LuhnValidator() {
        // Private constructor to prevent instantiation
    }

    /**
     * Validates a card number using the Luhn algorithm.
     *
     * <p>The Luhn algorithm, also known as the "modulus 10" or "mod 10" algorithm, is a simple checksum
     * formula used to validate a variety of identification numbers, such as credit card numbers,
     * Canadian Social Insurance Numbers, and more.</p>
     *
     * <p>The algorithm works as follows:</p>
     * <ol>
     *   <li>Starting from the rightmost digit (excluding the check digit) and moving left, double the value of every second digit.</li>
     *   <li>If doubling of a digit results in a two-digit number, add up the two digits to get a single-digit number (or subtract 9 from the product).</li>
     *   <li>Sum up all the digits in the resulting number.</li>
     *   <li>If the total modulo 10 is equal to 0 (if the total ends in zero) then the number is valid according to the Luhn formula; else it is not valid.</li>
     * </ol>
     *
     * @param cardNumber the card number to validate
     * @return true if the card number is valid according to the Luhn algorithm, false otherwise
     */
    public static boolean isValid(String cardNumber) {
        if (cardNumber == null || cardNumber.isEmpty()) {
            return false;
        }

        int sum = 0;
        boolean alternate = false;

        for (int i = cardNumber.length() - 1; i >= 0; i--) {
            int n = Character.digit(cardNumber.charAt(i), 10);
            if (n < 0) {
                return false; // Non-digit character found
            }

            if (alternate) {
                n *= 2;
                if (n > 9) {
                    n = (n % 10) + 1;
                }
            }
            sum += n;
            alternate = !alternate;
        }

        return (sum % 10 == 0);
    }
}